#include "http_common.h"

using namespace std;

size_t HttpTool::receive_data(void *contents, size_t size, size_t nmemb, void *stream) {
	string *str = (string*)stream;
	(*str).append((char*)contents, size*nmemb);
	return size * nmemb;
}

size_t HttpTool::writedata2file(void *ptr, size_t size, size_t nmemb, FILE *stream) {
	size_t written = fwrite(ptr, size, nmemb, stream);
	return written;
}

int HttpTool::downloadFile(QString url, QString fileName) {
	CURL *curl;
	FILE *fp;
	CURLcode res;
	res = curl_global_init(CURL_GLOBAL_ALL);
	if (CURLE_OK != res)
	{
		printf("init libcurl failed.");
		curl_global_cleanup();
		return -1;
	}
	curl = curl_easy_init();
	if (curl) {
		fp = fopen(fileName.toStdString().c_str(), "wb");
		res = curl_easy_setopt(curl, CURLOPT_URL, url.toStdString().c_str());
		if (res != CURLE_OK)
		{
			fclose(fp);
			curl_easy_cleanup(curl);
			return -1;
		}
		res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpTool::writedata2file);
		if (res != CURLE_OK) {
			fclose(fp);
			curl_easy_cleanup(curl);
			return -1;
		}
		res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
		if (res != CURLE_OK)
		{
			fclose(fp);
			curl_easy_cleanup(curl);
			return -1;
		}
		res = curl_easy_perform(curl);
		fclose(fp);
		if (res != CURLE_OK) {
			fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
			curl_easy_cleanup(curl);
			return -1;
		}
		curl_easy_cleanup(curl);
	}
	curl_global_cleanup();
	return 0;
}

CURLcode HttpTool::HttpGet(const std::string & strUrl, std::string & strResponse, int nTimeout) {
	CURLcode res;
	CURL* pCURL = curl_easy_init();

	if (pCURL == NULL) {
		return CURLE_FAILED_INIT;
	}

	curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str());
	//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
	curl_easy_setopt(pCURL, CURLOPT_NOSIGNAL, 1L);
	curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout);
	curl_easy_setopt(pCURL, CURLOPT_NOPROGRESS, 1L);
	curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, HttpTool::receive_data);
	curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse);
	res = curl_easy_perform(pCURL);
	curl_easy_cleanup(pCURL);
	return res;
}

CURLcode HttpTool::HttpPost(const std::string & strUrl, std::string szJson, std::string & strResponse, int nTimeout) {
	CURLcode res;
	char szJsonData[1024];
	memset(szJsonData, 0, sizeof(szJsonData));
	strcpy(szJsonData, szJson.c_str());
	CURL* pCURL = curl_easy_init();
	struct curl_slist* headers = NULL;
	if (pCURL == NULL) {
		return CURLE_FAILED_INIT;
	}

	CURLcode ret;
	ret = curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str());
	//    std::cout << ret << std::endl;

	ret = curl_easy_setopt(pCURL, CURLOPT_POST, 1L);
	headers = curl_slist_append(headers, "content-type:application/json");

	ret = curl_easy_setopt(pCURL, CURLOPT_HTTPHEADER, headers);

	ret = curl_easy_setopt(pCURL, CURLOPT_POSTFIELDS, szJsonData);
	//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
	ret = curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout);

	ret = curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, HttpTool::receive_data);

	ret = curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse);

	res = curl_easy_perform(pCURL);
	curl_easy_cleanup(pCURL);
	return res;
}

qint64 HttpTool::uploadFileSegment(QString url, QString id, QString fileName, QByteArray postData, qint64 filePos, qint64 size, qint64 fileSize) {
	CURLcode res;
	qint64 ret = -1;
	string response;
	struct curl_slist* headers = NULL;

	CURL* pCURL = curl_easy_init();
	if (pCURL == NULL) {
		return CURLE_FAILED_INIT;
	}

	res = curl_easy_setopt(pCURL, CURLOPT_URL, url.toStdString().c_str());

	QString contentDisposition = QString("Content-Disposition: attachment;filename=\"%1\"").arg(fileName.toStdString().c_str());
	QString contentRange = QString("Content-Range: bytes %1-%2/%3").arg(filePos).arg(filePos + size - 1).arg(fileSize);
	QString sessionId = QString("Session-ID: %1").arg(id);

	res = curl_easy_setopt(pCURL, CURLOPT_POST, 1L);
	headers = curl_slist_append(headers, contentDisposition.toStdString().c_str());
	headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
	headers = curl_slist_append(headers, contentRange.toStdString().c_str());
	headers = curl_slist_append(headers, sessionId.toStdString().c_str());
	res = curl_easy_setopt(pCURL, CURLOPT_HTTPHEADER, headers);
	res = curl_easy_setopt(pCURL, CURLOPT_POSTFIELDS, postData.data());
	res = curl_easy_setopt(pCURL, CURLOPT_POSTFIELDSIZE, size);
	res = curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, 3);
	res = curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, HttpTool::receive_data);
	res = curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&response);

	// 0-6291455/940548560
	res = curl_easy_perform(pCURL);
	curl_slist_free_all(headers);
	curl_easy_cleanup(pCURL);

	if (res == 0)
	{
		QString resp = QString::fromStdString(response);
		if (resp.contains("code") && resp.contains("1000"))
		{
			ret = fileSize;
		}
		else
		{
			QString serverFileSize = resp.split("/")[0].split("-")[1];
			ret = serverFileSize.toLongLong();
		}
	}

	return ret;
}

CURLcode HttpTool::uploadFileSegment(const std::string & strUrl, std::string data, std::string & strResponse, int nTimeout) {
	CURLcode res;

	char postData[SEGMENT_SIZE];
	memset(postData, 0, sizeof(postData));
	strcpy(postData, data.c_str());

	struct curl_slist* headers = NULL;

	CURL* pCURL = curl_easy_init();
	if (pCURL == NULL) {
		return CURLE_FAILED_INIT;
	}

	CURLcode ret;
	ret = curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str());

	ret = curl_easy_setopt(pCURL, CURLOPT_POST, 1L);
	headers = curl_slist_append(headers, "Content-Disposition: attachment;filename=\"ccc.mp4\"");
	headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
	headers = curl_slist_append(headers, "Content-Range: bytes 0-8/9");
	headers = curl_slist_append(headers, "Session-ID: 3e8e02fc506fa535eecfe0965e1a2029");

	ret = curl_easy_setopt(pCURL, CURLOPT_HTTPHEADER, headers);

	ret = curl_easy_setopt(pCURL, CURLOPT_POSTFIELDS, postData);
	//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
	ret = curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout);

	ret = curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, HttpTool::receive_data);

	ret = curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse);

	res = curl_easy_perform(pCURL);
	curl_slist_free_all(headers);
	curl_easy_cleanup(pCURL);
	return res;
}